<?php

namespace App\Service\Cruise\CruiseProject;

use App\Enums\BaseErrorCode;
use App\Exceptions\Custom\ResponseHttpException;
use App\Models\Common\ResourcesModel;
use App\Models\Cruise\CruiseProjectCategoryModel;
use App\Models\Cruise\CruiseTaskProjectModel;
use App\Models\Cruise\CruiseTemplatePositionProjectMappingModel;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Overtrue\Pinyin\Pinyin;

class CruiseProjectService
{
    private function getModel(int $id): CruiseTaskProjectModel
    {
        $model = CruiseTaskProjectModel::query()->find($id);
        if (!$model) {
            throw new ResponseHttpException(BaseErrorCode::$ERROR_OCCURRED, null, "不存在的项目");
        }

        return $model;
    }

    /**
     * 新增/编辑
     * @param CruiseProjectParam $param
     * @return int
     */
    public function addOrEdit(CruiseProjectParam $param, int $id): int
    {
        if ($id) {
            $model      = $this->getModel($id);
            $inputField = $model->inputField;
        } else {
            $name       = mb_substr($param->getName(), 0, 6); // 太长了，截取前6
            $inputField = (new Pinyin())->permalink($name, '_') . '_' . Str::random(6);
            $id         = CruiseBaseService::popId(new CruiseTaskProjectModel());
        }

        $inputObject = (new CruiseProjectInputService($param->getInputType(), $inputField, $param->getName()))
            ->setRequired($param->getRequired())
            ->setOptions($param->getOptions())
            ->setMaxContentLength($param->getMaxContentLength())
            ->setRichShow($param->getRichShow())
            ->setMeanType($param->getMeanType())
            ->setProjectId($id)
            ->prepareAttribute();

        $data = [
            'categoryId'  => $param->getCategoryId(),
            'name'        => $param->getName(),
            'tipsType'    => $param->getTipsType(),
            'tipsContent' => $param->getTipsContent(),
            'status'      => $param->getStatus(),
            'inputType'   => $param->getInputType(),
            'inputObject' => serialize($inputObject),
            'inputField'  => $inputField,
            'meanType'    => $param->getMeanType(),
            'richShow'    => $param->getRichShow(),
        ];

        DB::beginTransaction();
        $id = CruiseTaskProjectModel::query()->updateOrCreate(['id' => $id], $data)->id;

        if ($param->getTipsResource()) {
            $tipsResource = collect($param->getTipsResource())->map(function ($item) {
                $item = ltrim(parse_url($item, PHP_URL_PATH), '/');
                return $item;
            })->toArray();

            ResourcesModel::moduleBusinessSingleResourcesUpdate(
                ResourcesModel::MODULE_TYPE_CRUISE,
                ResourcesModel::BUSINESS_CRUISE_PROJECT_TIPS,
                'tipsResource', $id,
                $tipsResource,
                1
            );
        }

        DB::commit();

        return $id;
    }

    /**
     * 停用
     * @param int $id
     * @return int
     */
    public function offline(CruiseProjectParam $param, int $id): int
    {
        $this->getModel($id);

        return CruiseTaskProjectModel::query()
                                     ->where('id', $id)
                                     ->update(['status' => $param->getStatus()]);
    }

    /**
     * 删除
     * @param int $id
     * @return int
     */
    public function delete(int $id): void
    {
        $this->getModel($id);

        DB::beginTransaction();
        CruiseTaskProjectModel::query()->where('id', $id)->update(['isDeleted' => 1]);
        CruiseTemplatePositionProjectMappingModel::query()->where('projectId', $id)->delete();
        DB::commit();
    }

    /**
     * 列表
     * @param CruiseProjectParam $param
     * @return array
     */
    public function lists(CruiseProjectParam $param, array $types): array
    {
        $categoryIds = CruiseProjectCategoryModel::query()->whereIn('type', $types)->pluck('id');

        $paginator = CruiseTaskProjectModel::query()
                                           ->when($param->getCategoryId(), function ($query) use ($param) {
                                               $categoryIds = CruiseProjectCategoryModel::query()
                                                                                        ->where('pid',
                                                                                            $param->getCategoryId())
                                                                                        ->pluck('id')
                                                                                        ->toArray();

                                               $categoryIds[] = $param->getCategoryId();

                                               $query->whereIn('categoryId', $categoryIds);
                                           })
                                           ->when($param->getName(), function ($query) use ($param) {
                                               $query->where('name', "like", "%{$param->getName()}%");
                                           })
                                           ->whereIn('categoryId', $categoryIds)
                                           ->orderByDesc('status')
                                           ->orderBy('id')
                                           ->paginate($param->getPageSize(), ['*'], 'pageNum', $param->getPageNum());

        return [
            'count'    => $paginator->total(),
            'list'     => $paginator->map(function ($item) {
                return [
                    'id'            => $item->id,
                    'name'          => $item->name,
                    'status'        => $item->status,
                    'statusText'    => $item->statusText,
                    'inputType'     => $item->inputType,
                    'inputTypeText' => $item->inputTypeText,
                    'options'       => $item->optionsArr,
                    'required'      => $item->required,
                ];
            }),
            'pageNum'  => $param->getPageNum(),
            'pageSize' => $param->getPageSize(),
        ];
    }

    /**
     * 详情
     * @param int $id
     * @return array
     */
    public function detail(int $id): array
    {
        $item = $this->getModel($id);

        $resource = ResourcesModel::getModuleBusinessResources(ResourcesModel::MODULE_TYPE_CRUISE,
            ResourcesModel::BUSINESS_CRUISE_PROJECT_TIPS, $item->id, ['tipsResource']);

        return [
            'id'               => $item->id,
            'categoryId'       => $item->categoryId,
            'categoryPid'      => (int)CruiseProjectCategoryModel::query()
                                                                 ->where('id', $item->categoryId)
                                                                 ->value('pid'),
            'required'         => $item->required,
            'name'             => $item->name,
            'status'           => $item->status,
            'inputType'        => $item->inputType,
            'options'          => $item->optionsArr,
            'tipsType'         => $item->tipsType,
            'tipsContent'      => $item->tipsContent,
            'tipsResource'     => $resource->tipsResource ?? [],
            'maxContentLength' => $item->maxContentLength,
            'meanType'         => $item->meanType,
            'richShow'         => $item->richShow,
        ];
    }
}
